package com.ncr.travel.appmgr.service.converter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.ncr.travel.appmgr.model.ProductCategoryJson;
import com.ncr.travel.appmgr.model.ProductJson;
import com.ncr.travel.appmgr.model.ScreenJson;
import com.ncr.travel.appmgr.model.shared.Product;
import com.ncr.travel.appmgr.model.shared.ProductCategory;
import com.ncr.travel.appmgr.model.shared.Screen;
import com.ncr.travel.tas.configuration.model.ConfigurationNode;
import com.ncr.travel.tas.configuration.model.ConfigurationValue;
import com.ncr.travel.tas.shared.configuration.ConfigurationKey;

@Component
public class ProductConverterImpl implements ProductConverter {

	private static final Logger logger = LoggerFactory.getLogger(ProductConverterImpl.class);

	public ProductConverterImpl() {
		super();
	}

	@Override
	public Product getProduct(ConfigurationNode configNode) {

		Product product = new ProductJson();
		product.setId((int)configNode.getId());
		product.setName(configNode.getName());
		ConfigurationValue productConfig = configNode.getConfigurations().iterator().next();
		product.setKey(productConfig.getKeyName());
		Set<ConfigurationValue> configValues = productConfig.getChildValues();

		List<ProductCategory> categories = new ArrayList<ProductCategory>();

		for (ConfigurationValue value : configValues) {
			ProductCategory category = createCategory(value);
			categories.add(category);
		}

		product.setCategories(categories);

		return product;
	}

	@Override
	public List<Product> getProducts(Set<ConfigurationValue> productContainers) {

		List<Product> products = new ArrayList<Product>();

		ConfigurationValue productRoot = (ConfigurationValue) productContainers.toArray()[0];

		// we should only have one node for the Application Manager
		for (ConfigurationValue productNode : productRoot.getChildValues()) {

			logger.debug("productNode.keyName = '" + productNode.getKeyName() + "'");
			try {
				logger.debug("productNode.tag = '" + productNode.getTag() + "'");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			logger.debug("productNode.value = '" + productNode.getValue() + "'");

			// create the new product
			Product product = new ProductJson();
			try {
				product.setName((String) productNode.getTag());
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			product.setId((int)productNode.getId());
			product.setKey(productNode.getKeyName());
			product.setThemeId(productNode.getValue().toString());
			products.add(product);

			// bucket for the category bucket. Should only be one of these
			List<ProductCategory> categories = new ArrayList<ProductCategory>();

			for (ConfigurationValue categoryValue : productNode.getChildValues()) {

				// add a category to the category array
				ProductCategory productCategoryValue = this.createCategory(categoryValue);
				categories.add(productCategoryValue);

				// do we have any screens?
				if (categoryValue.getChildValues().size() > 0) {

					List<Screen> screens = new ArrayList<Screen>();

					// do the domain mapping here from ConfigurationApi to
					// AppMgr object domain
					for (ConfigurationValue value : categoryValue.getChildValues()) {
						Screen screen = createScreen(value);
						if (screen != null) {
							screens.add(screen);
						}
					}
					if (!screens.isEmpty()) {
						productCategoryValue.setScreens(screens);
					}
				}
			}
			product.setCategories(categories);
		}

		return products;
	}

	private ProductCategory createCategory(ConfigurationValue categoryValue) {

		logger.debug("categoryValue.keyName = '" + categoryValue.getKeyName() + "'");
		try {
			logger.debug("categoryValue.tag = '" + categoryValue.getTag() + "'");
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		logger.debug("categoryValue.value = '" + categoryValue.getValue() + "'");

		// create a product category and initialize it
		ProductCategory category = new ProductCategoryJson();
		category.setId((int)categoryValue.getId());
		category.setKey(categoryValue.getKeyName());
		try {
			category.setName((String) categoryValue.getTag());
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		// next level down are screens
		if (categoryValue.getChildValues().size() > 0) {

			// for each screen, add it to the collection
			for (ConfigurationValue categoryChildValue : categoryValue.getChildValues()) {

				logger.debug("categoryChildValue.keyName = '" + categoryChildValue.getKeyName() + "'");
				try {
					logger.debug("categoryChildValue.tag = '" + categoryChildValue.getTag() + "'");
				} catch (Exception e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				logger.debug("categoryChildValue.value = '" + categoryChildValue.getValue() + "'");

				List<Screen> screens = new ArrayList<Screen>();

				for (ConfigurationValue screenValue : categoryChildValue.getChildValues()) {

					Screen screen = createScreen(screenValue);
					if (screen == null) {
						continue;
					}
					screens.add(screen);

					// check to see if there are child-screen values
					if (screenValue.getChildValues().size() > 0) {

						for (ConfigurationValue childScreenConfigValue : screenValue.getChildValues()) {

							logger.debug("childScreenConfigValue.keyName = '" + childScreenConfigValue.getKeyName() + "'");
							try {
								logger.debug("childScreenConfigValue.tag = '" + childScreenConfigValue.getTag() + "'");
							} catch (Exception e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
							logger.debug("childScreenConfigValue.value = '" + childScreenConfigValue.getValue() + "'");

							List<Screen> childScreens = new ArrayList<Screen>();

							// cycle through and dig out the subscreens
							for (ConfigurationValue childScreenValue : childScreenConfigValue.getChildValues()) {
								Screen childScreen = createScreen(childScreenValue);
								if (childScreen != null) {
									childScreens.add(childScreen);
								}
							}

							if (!childScreens.isEmpty()) {
								// attach to parent screen
								screen.setChildScreens(childScreens);
							}
						}
					}

				}
				if (!screens.isEmpty()) {
					// attach to parent category
					category.setScreens(screens);
				}
			}
		}
		return category;
	}

	private Screen createScreen(ConfigurationValue screenValue) {

		if (screenValue.getKeyName().equals(ConfigurationKey.FUNCTIONS.toString()) || screenValue.getKeyName().equals(ConfigurationKey.RULES.toString())
				|| screenValue.getKeyName().equals(ConfigurationKey.TEXT.toString())) {
			logger.debug("SKIPPING BECAUSE KEY = " + screenValue.getKeyName());
			return null;
		}

		logger.debug("screenValue.keyName = '" + screenValue.getKeyName() + "'");
		try {
			logger.debug("screenValue.tag = '" + screenValue.getTag() + "'");
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		logger.debug("screenValue.value = '" + screenValue.getValue() + "'");

		Screen screen = new ScreenJson();
		screen.setId((int)screenValue.getId());
		screen.setKey(screenValue.getKeyName());
		try {
			screen.setName((String) screenValue.getTag());
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		// check for any sub-screens
		if (screenValue.getChildValues().size() > 0) {

			List<Screen> subscreens = new ArrayList<Screen>();

			for (ConfigurationValue subScreenValue : screenValue.getChildValues()) {
				if (subScreenValue.getKeyName().equals(ConfigurationKey.FUNCTIONS.toString()) || subScreenValue.getKeyName().equals(ConfigurationKey.RULES.toString())
						|| subScreenValue.getKeyName().equals(ConfigurationKey.TEXT.toString())) {
					logger.debug("SKIPPING BECAUSE KEY = " + subScreenValue.getKeyName());
					break;
				}
				logger.debug("subScreenValue.keyName = '" + subScreenValue.getKeyName() + "'");
				if (subScreenValue.getTag() != null) {
					try {
						logger.debug("subScreenValue.tag = '" + subScreenValue.getTag().toString() + "'");
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				logger.debug("subScreenValue.value = '" + subScreenValue.getValue() + "'");
				Screen childScreen = new ScreenJson();
				childScreen.setId((int)subScreenValue.getId());
				childScreen.setKey(subScreenValue.getKeyName());
				if (subScreenValue.getTag() != null) {
					try {
						childScreen.setName(subScreenValue.getTag().toString());
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				subscreens.add(childScreen);
			}
			if (!subscreens.isEmpty()) {
				screen.setChildScreens(subscreens);
			}
		}
		return screen;
	}

	private void createText(ConfigurationValue screen) {
		// TODO Auto-generated method stub

	}

	@Override
	public List<ProductCategory> getProductCategories(String productName) {

		List<ProductCategory> productCategories = new ArrayList<ProductCategory>();
		List<String> categoriesNameList = Arrays.asList("Global", "Base Check-in App", "International Doc Entry", "Fee Module");
		for (int counter = 0; counter <= 3; counter++) {
			ProductCategory productCategory = new ProductCategoryJson();
			productCategory.setKey(categoriesNameList.get(counter));
			productCategory.setName(categoriesNameList.get(counter));
			List<String> screenNames = new ArrayList<String>();
			for (int i = 0; i <= 3; i++) {

				screenNames.add("Screen-" + counter + i);
			}
			productCategories.add(productCategory);
		}
		return productCategories;
	}

}
